<template>
  <div class="content-container">
    <div class="cc-left">
      <div class="ccl-title">对话列表</div>
      <div v-loading="groupLoading" class="lists">
        <el-badge
          :value="item.unreadCount"
          :hidden="!item.unreadCount"
          :offset="[-25, -6]"
          :class="[
            'list',
            {
              active: groupId === item.id
            }
          ]"
          v-for="item in groupList"
          :key="item.id"
          @click="handleSessionClick(item)"
        >
          <img
            :src="item.avatar || avatarImg"
            class="avatar"
            @error="handleImageError"
          />
          <span>{{ item.title }}</span>
        </el-badge>
      </div>
    </div>
    <div class="cc-right">
      <el-row
        type="flex"
        justify="end"
        class="header-filter four-border-blueBg"
      >
        <el-button type="primary" @click="handleDeleteSession">{{
          $t('push.deleteSession')
        }}</el-button>
        <el-button @click="handleCreateSession">{{
          $t('push.createSession')
        }}</el-button>
      </el-row>
      <div class="base-table-container">
        <div class="chat-items" ref="refChatItems">
          <div v-if="msgLoading" class="no-msg">正在加载历史消息~~</div>
          <div v-else-if="!msgList.length" class="no-msg">暂无更多消息~~</div>
          <TextMsgView
            v-for="item in msgList"
            :row="item"
            :key="item.id"
            @menu="hanldeContextMenu(item)"
            @delete="handleDelete(item)"
            @recall="handleRecall(item)"
            @quote="hanldeQuote(item)"
          />
        </div>
        <div class="input-container">
          <div class="message-input-toolbar-list">
            <customEmojiPicker @select="onSelectEmoji" />
            <ImageUpload @sendImage="handleSendImage" />
            <FileUpload @sendFile="handleSendFile" />
          </div>
          <MsgInput
            ref="refTextInput"
            v-model="textInput"
            @enter="handleSend"
            @sendImage="handleSendImage"
            @sendFile="handleSendFile"
          />
          <QuoteView v-model="quoteMsg" type="1" />
          <el-button
            class="send-btn"
            type="primary"
            :loading="sendLoading"
            @click="handleSend"
            >{{ $t('push.send') }}</el-button
          >
        </div>
      </div>
    </div>
    <AddSession v-if="addVisible" v-model="addVisible" @update="getGroupList" />
  </div>
</template>

<script setup>
import avatarImg from '@/assets/avatar.png'

import AddSession from './component/AddSession.vue'
import TextMsgView from './component/TextMsgView.vue'
import customEmojiPicker from './component/EmojiPicker.vue'
import ImageUpload from './component/ImageUpload.vue'
import FileUpload from './component/FileUpload.vue'
import MsgInput from './component/MsgInput.vue'
import QuoteView from './component/QuoteView.vue'

const userStore = useUserStore()
const { userInfo, eventSource } = storeToRefs(userStore)
const groupLoading = ref(false)
const groupList = ref([])
const groupId = ref('')
const groupToId = ref('')
const unreadCount = ref(0)
// 聊天参数
const refChatItems = ref(null)
const msgLoading = ref(false)
const msgList = ref([])
const refTextInput = ref(null)
const textInput = ref('')
const quoteMsg = ref('')
const sendLoading = ref(false)
const addVisible = ref(false)
// 取消请求参数
const controller = ref(null)
const timer = ref(null)

watch(
  () => groupToId.value,
  nv => {
    console.log('groupToId.value', nv)
    getChatMsg()
  }
)

watch(
  () => msgList.value.length,
  (nv, ov) => {
    if (nv !== ov) {
      nextTick(() => {
        scrollToBottom()
        if (unreadCount.value) unreadCountZero()
      })
    }
  },
  {
    deep: true
  }
)

onMounted(async () => {
  // console.log(history.state, history.state.params)
  eventSource.value.on('chat-message', chatMsgDeal)
  eventSource.value.on('chat-dialog', chatDialogDeal)
  await getGroupList()
  const { tenantId } = history.state.params || {}
  // 未发现tenantId则创建会话
  let found = groupList.value.find(item => item.memberList.includes(tenantId))
  if (!found && tenantId) {
    await createSession()
    await getGroupList()
    found = groupList.value.find(item => item.memberList.includes(tenantId))
  }
  if (tenantId) {
    // 清除history.state的参数值
    const newState = { ...history.state }
    delete newState.params.tenantId
    history.replaceState(newState, '', window.location.href)
  }
  if (!found) found = groupList.value[0]
  groupId.value = found?.id || ''
  groupToId.value = found?.toId || ''
  // await getChatMsg()
})

onBeforeUnmount(() => {
  // 如果存在未完成的请求，则取消它
  if (controller.value) {
    controller.value.abort()
    console.log('controller.value-取消未完成的请求!')
  }
  eventSource.value.off('chat-message', chatMsgDeal)
  eventSource.value.off('chat-dialog', chatDialogDeal)
  clearTimeout(timer.value)
})

const unreadCountZero = _ => {
  return g_api.sysMsg
    .apiDialogUnreadCountZero({
      userId: userInfo.value.userId,
      toId: groupToId.value
    })
    .then(({ code, data }) => {})
    .finally(() => {})
}

const handleImageError = e => {
  console.log('handleImageError')
  // 替换为备用图片
  e.target.src = avatarImg
}

const chatMsgDeal = event => {
  // console.log('on chat-message', event)
  nextTick(() => {
    const data = JSON.parse(event.data).data
    console.log('chat-message-data', data)
    if (data.toId !== groupToId.value) return
    const foundItem = msgList.value.find(item => {
      return (
        String(item.id) === String(data.id) ||
        (data.tagId && String(item.tagId) === String(data.tagId))
      )
    })
    data.sending = false
    if (foundItem) {
      // 如果找到相同id或tagId的项，合并数据
      Object.assign(foundItem, data)
    } else {
      msgList.value.push(data)
    }
  })
}

const chatDialogDeal = event => {
  const data = JSON.parse(event.data).data
  console.log('chat-dialog-data', data)
  groupList.value.unshift(data)
  groupId.value = groupList.value[0]?.id || ''
  groupToId.value = groupList.value[0]?.toId || ''
}

const getGroupList = (loading = true) => {
  groupLoading.value = loading
  return g_api.sysMsg
    .apiDialogList({
      userId: userInfo.value.userId,
      pageNum: 1,
      pageSize: 30
    })
    .then(({ code, data }) => {
      if (code === '200' && data) {
        // console.log('apiDialogList', data)
        groupList.value = data.items
        groupId.value = groupId.value || groupList.value[0]?.id || ''
        groupToId.value = groupToId.value || groupList.value[0]?.toId || ''
        unreadCount.value = groupList.value[0]?.unreadCount || 0
        // getChatMsg()
      }
    })
    .finally(() => {
      groupLoading.value = false
      timedFetch()
    })
}

const timedFetch = () => {
  clearTimeout(timer.value)
  timer.value = setTimeout(_ => {
    getGroupList(false)
  }, 10 * 1000)
}

const createSession = _ => {
  return g_api.sysMsg
    .apiDialogCreate({
      fromId: userInfo.value.userId,
      toTenantId: history.state.params.tenantId,
      type: 'group'
    })
    .then(res => {
      if (res.code === '200') {
        ElMessage({
          message: res.message,
          type: 'success'
        })
      }
    })
}

const getChatMsg = () => {
  msgLoading.value = true
  msgList.value = []
  // 如果存在未完成的请求，则取消它
  if (controller.value) {
    controller.value.abort()
    console.log('controller.value-取消未完成的请求!')
  }
  // 创建新的 AbortController
  controller.value = new AbortController()
  return g_api.sysMsg
    .apiMsgList(
      {
        userId: userInfo.value.userId,
        toId: groupToId.value,
        source: 'group',
        pageNum: 1,
        pageSize: 300
      },
      {},
      {
        signal: controller.value.signal
      }
    )
    .then(({ code, data }) => {
      if (code === '200' && data) {
        msgList.value = data.items
      }
    })
    .finally(() => {
      msgLoading.value = false
    })
}

const sendChatMsg = msgBody => {
  console.log('sendChatMsg', msgBody)
  sendLoading.value = true
  // 如果消息已断开，就重新链接一次
  // if (eventSource.value.eventSource.readyState === 2) {
  //   userStore.startSSEClient()
  //   eventSource.value.on('chat-message', chatMsgDeal)
  //   eventSource.value.on('chat-dialog', chatDialogDeal)
  // }
  msgList.value.push({
    ...msgBody,
    sending: true
  })
  g_api.sysMsg
    .apiMsgCreate(msgBody)
    .then(({ code, data }) => {
      // if (code === '200' && data) {
      // }
    })
    .finally(() => {
      sendLoading.value = false
      textInput.value = ''
      quoteMsg.value = ''
    })
}

const scrollToBottom = () => {
  setTimeout(() => {
    if (!refChatItems.value) return
    refChatItems.value.scrollTop =
      refChatItems.value.scrollHeight - refChatItems.value.offsetHeight
  })
}

const handleSessionClick = item => {
  groupId.value = item.id
  groupToId.value = item.toId
  unreadCount.value = item.unreadCount
  // getChatMsg()
}

const handleDeleteSession = () => {
  g_utils
    .deleteConfirm()
    .then(() => {
      groupLoading.value = true
      g_api.sysMsg
        .apiDialogDelete({
          id: groupId.value
        })
        .then(res => {
          if (res.code === '200') {
            ElMessage.success(res.message)
            getGroupList()
          }
        })
        .finally(() => {
          groupLoading.value = false
        })
    })
    .catch(() => {})
}

const handleCreateSession = () => {
  addVisible.value = true
  quoteMsg.value = ''
}

const hanldeContextMenu = row => {
  console.log('hanldeContextMenu', row)
  msgList.value = msgList.value.map(item => {
    if (item.id === row.id) {
      item.contextMenuVisible = true
    } else {
      item.contextMenuVisible = false
    }
    return item
  })
}

const handleDelete = row => {
  console.log('handleDelete', row)
  msgList.value = msgList.value.filter(item => {
    return item.id !== row.id
  })
  quoteMsg.value = ''
}

const handleRecall = row => {
  for (const item of msgList.value) {
    if (item.id === row.id) {
      item.sending = true
      break
    }
  }
}

const hanldeQuote = row => {
  console.log('hanldeQuote', row)
  quoteMsg.value = row
}

const onSelectEmoji = emoji => {
  const msgLength = emoji.native.length
  const inputEl = refTextInput.value?.refNwMsgInput
  if (inputEl) {
    const startPos = inputEl.selectionStart
    textInput.value = `${textInput.value.slice(0, startPos)}${
      emoji.native
    }${textInput.value.slice(startPos)}`
    refTextInput.value.focus()
    nextTick(() => {
      // 此处是根据元素的长度，来设置光标位置
      inputEl.setSelectionRange(startPos + msgLength, startPos + msgLength)
    })
  }
}

const handleSendMsg = () => {
  return {
    fromId: userInfo.value.userId,
    toId: groupToId.value,
    fromInfo: {
      id: userInfo.value.userId,
      name: userInfo.value.nickName,
      avatar: userInfo.value.avatar || '',
      type: 'group'
    },
    // message: '{"content":"你好，我想订车"}',
    referenceMsg: quoteMsg.value || undefined,
    // atUser: {
    //   id: '0ff09f3a80324ffabc76c90bc1b5af0e',
    //   name: '张三',
    //   avatar: 'https://file.neoway.com/d/private/images/flower.jpg'
    // },
    source: 'group',
    tagId: Date.now(),
    createTime: g_dayjs().format('YYYY-MM-DD HH:mm:ss')
    // contextMenuVisible: false // 右键菜单是否可见
  }
}

const uploadFile = (files, type) => {
  const file = files[0]
  // console.log(file)
  sendLoading.value = true
  const formData = new FormData()
  formData.append('file', file)

  g_api.travelAgency
    .apiFileUpload(formData, {
      'Content-Type': 'multipart/form-data' // 关键！
    })
    .then(({ code, data }) => {
      if (code === '200' && data) {
        sendChatMsg({
          ...handleSendMsg(),
          type,
          message: JSON.stringify({
            url: data.url,
            name: file.name,
            size: file.size
          })
        })
      }
    })
    .finally(() => {
      sendLoading.value = false
    })
}

const handleSendImage = files => {
  uploadFile(files, 'photo')
  // const file = files[0]
  // // 创建 FileReader 对象
  // const reader = new FileReader()
  // // 读取文件内容（Base64 格式）
  // reader.readAsDataURL(file)
  // // 读取文件完成后的回调
  // reader.onload = e => {
  //   // console.log('e', e, e.target.result)
  //   sendChatMsg({
  //     ...handleSendMsg(),
  //     type: 'photo',
  //     message: JSON.stringify({
  //       url: e.target.result,
  //       name: file.name,
  //       size: file.size
  //     })
  //   })
  // }
}

const handleSendFile = files => {
  uploadFile(files, 'file')
}

const handleSend = () => {
  console.log('handleSend', textInput.value)
  if (!sendLoading.value && textInput.value.trim()) {
    sendChatMsg({
      ...handleSendMsg(),
      type: 'text',
      message: JSON.stringify({
        content: textInput.value
      })
    })
    textInput.value = ''
    quoteMsg.value = ''
  }
}
</script>

<style lang="scss" scoped>
.content-container {
  flex-direction: row;
}
.cc-left,
.cc-right {
  display: flex;
  flex-direction: column;
}
.cc-left {
  width: 20%;
  min-width: 120px;
  max-width: 250px;
  margin-right: 5px;
  padding: 10px 0;
  background-color: #fff;
  .ccl-title {
    padding: 0 16px;
    font-family: Arial;
    font-size: 14px;
    font-weight: 600;
    color: #333;
  }
  .lists {
    height: 100%;
    display: flex;
    flex-direction: column;
    margin-top: 10px;
    overflow-y: auto;
    .list {
      cursor: pointer;
      width: 100%;
      padding: 10px 10px;
      display: flex;
      align-items: center;
      font-size: 14px;
      color: #333;
      box-sizing: border-box;
      border-bottom: 1px solid #dcdfe6;
      &:hover {
        font-weight: 600;
        background-color: #ecf5ff;
      }
      &.active {
        font-weight: 600;
        background-color: #ecf5ff;
      }
      .avatar {
        width: 20px;
        height: 20px;
        margin-right: 5px;
        border-radius: 50%;
      }
    }
  }
}
.cc-right {
  flex: 1;
  margin-left: 5px;
}

.base-table-container {
  display: flex;
  flex-direction: column;
}
.chat-items {
  flex: 1;
  overflow-y: auto;
  padding-bottom: 10px;
  .no-msg {
    text-align: center;
    font-size: 12px;
    color: #666;
  }
}
.message-input-toolbar-list {
  display: flex;
  flex-direction: row;
  align-items: center;
  :deep() {
    .toolbar-item-container {
      position: relative;
    }
    .toolbar-item-container-icon {
      cursor: pointer;
      padding: 8px;
      display: flex;
    }
    .common-icon {
      width: 20px;
      height: 20px;
    }
  }
}
.input-container {
  position: relative;
  background-color: #fff;
  box-shadow: 0 0 0 1px #dcdfe6;
  border-radius: 4px;
  .send-btn {
    position: absolute;
    bottom: 5px;
    right: 5px;
    padding: 5px 15px;
  }
}
</style>
